package com.qingzhuge.scheduler.job;

import com.qingzhuge.cache.RedisLockUtil;
import com.qingzhuge.common.utils.MathUtil;
import com.qingzhuge.context.SpringContext;
import com.qingzhuge.scheduler.dto.request.TaskJobKey;
import com.qingzhuge.scheduler.entity.SysTaskScheduled;
import com.qingzhuge.scheduler.service.ISchedulerService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

import static com.qingzhuge.scheduler.entity.SysTaskScheduled.JOB_DATA_MAP_SCHEDULED;

/**
 * @author : zero.xiao
 * @description : 默认调度(非阻塞)
 * @date :2019-05-17 11:19
 * @modified :
 */
@Slf4j
public class BaseJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        long start = System.currentTimeMillis();
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        SysTaskScheduled scheduled = (SysTaskScheduled) jobDataMap.get(JOB_DATA_MAP_SCHEDULED);
        if (null != scheduled) {
            String targetObject = scheduled.getTargetObject();
            String targetMethod = scheduled.getTargetMethod();
            if (null != targetObject && null != targetMethod) {
                Long scheduledId = scheduled.getId();
                String key = String.format("task:%s:%s:%s", targetObject, targetMethod, scheduledId);
                try {
                    log.info("定时任务[{}.{}]开始", targetObject, targetMethod);
                    if (lock(key,scheduledId.toString())) {
                        try {
                            Object refer = SpringContext.getBean(targetObject);
                            if (null != refer) {
                                refer.getClass().getDeclaredMethod(targetMethod).invoke(refer);
                                double time = (System.currentTimeMillis() - start) / 1000.0;
                                log.info("定时任务[{}.{}]用时：{}s", targetObject, targetMethod, time);
                            }
                        } finally {
                            unLock(key,scheduledId.toString());
                        }
                    }
                } catch (Exception e) {
                    throw new JobExecutionException(e);
                }
            } else {
                log.warn("错误的定时任务[{}.{}]", targetObject, targetMethod);
                log.warn("删除任务错误的定时任务 scheduled：{}", scheduled);
                ISchedulerService schedulerService = SpringContext.getBean(ISchedulerService.class);
                if (null != schedulerService) {
                    TaskJobKey jobKey = schedulerService.getTaskJobKey(scheduled);
                    schedulerService.delTask(jobKey);
                }
            }
        } else {
            Trigger trigger = context.getTrigger();
            String group = trigger.getKey().getGroup();
            String name = trigger.getKey().getName();
            ISchedulerService schedulerService = SpringContext.getBean(ISchedulerService.class);
            if (null != schedulerService) {
                TaskJobKey jobKey = new TaskJobKey(name, group);
                schedulerService.delTask(jobKey);
                log.warn("删除任务错误的定时任务 scheduled is null");
            }
        }
    }

    private Boolean lock(String key, String requestId) {
        return RedisLockUtil.getRedisLock().lock(key, requestId);
    }

    private void unLock(String key, String requestId) {
        try {
            RedisLockUtil.getRedisLock().unLock(key, requestId);
        } catch (Exception e) {
            log.error("", e);
            try {
                Thread.sleep(MathUtil.getRandom(100, 2000).longValue());
            } catch (Exception e2) {
                log.error("", e2);
            }
            RedisLockUtil.getRedisLock().unLock(key, requestId);
        }
    }
}
